<!DOCTYPE html>
<html>
<head>
    

    

    



    <meta charset="utf-8">
    
    
    
    
    <title>阻塞队列——ArrayBlockingQueue源码分析 | 博客主页 | 世界是个球，前方总有路！</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <meta name="theme-color" content="#3F51B5">
    
    
    <meta name="keywords" content="Java容器">
    <meta name="description" content="一、前言&amp;emsp;&amp;emsp;这几天准备研究一下Java中阻塞队列的实现。Java中的阻塞队列有七种，我准备逐一研究它们的源码，然后每一个阻塞队列写一篇分析博客，这是其中的第一篇。这篇博客就来说一说阻塞队列中我认为应该是最简单的一种——ArrayBlockingQueue。   二、正文2.1 什么是阻塞队列&amp;emsp;&amp;emsp;在正式分析前，先简单介绍一下什么是阻塞队列。在说阻塞队列前，先要">
<meta property="og:type" content="article">
<meta property="og:title" content="阻塞队列——ArrayBlockingQueue源码分析">
<meta property="og:url" content="http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/index.html">
<meta property="og:site_name" content="博客主页">
<meta property="og:description" content="一、前言&amp;emsp;&amp;emsp;这几天准备研究一下Java中阻塞队列的实现。Java中的阻塞队列有七种，我准备逐一研究它们的源码，然后每一个阻塞队列写一篇分析博客，这是其中的第一篇。这篇博客就来说一说阻塞队列中我认为应该是最简单的一种——ArrayBlockingQueue。   二、正文2.1 什么是阻塞队列&amp;emsp;&amp;emsp;在正式分析前，先简单介绍一下什么是阻塞队列。在说阻塞队列前，先要">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-04-11T09:22:03.000Z">
<meta property="article:modified_time" content="2020-04-11T16:51:51.414Z">
<meta property="article:author" content="特务依昂">
<meta property="article:tag" content="Java容器">
<meta name="twitter:card" content="summary">
    
        <link rel="alternate" type="application/atom+xml" title="博客主页" href="/blog/atom.xml">
    
    <link rel="shortcut icon" href="/blog/img/title.png">
    <link rel="stylesheet" href="//unpkg.com/hexo-theme-material-indigo@latest/css/style.css">
    <script>window.lazyScripts=[]</script>

    <!-- custom head -->
    

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
    <div id="loading" class="active"></div>

    <aside id="menu" class="hide" >
  <div class="inner flex-row-vertical">
    <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menu-off">
        <i class="icon icon-lg icon-close"></i>
    </a>
    <div class="brand-wrap" style="background-image:url(/blog/img/brand.jpg)">
      <div class="brand">
        <a href="/blog/" class="avatar waves-effect waves-circle waves-light">
          <img src="/blog/img/avatar.jpg">
        </a>
        <hgroup class="introduce">
          <h5 class="nickname">特务依昂</h5>
          <a href="mailto:1131564805@qq.com" title="1131564805@qq.com" class="mail">1131564805@qq.com</a>
        </hgroup>
      </div>
    </div>
    <div class="scroll-wrap flex-col">
      <ul class="nav">
        
            <li class="waves-block waves-effect">
              <a href="/blog/"  >
                <i class="icon icon-lg icon-home"></i>
                主页
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/archives"  >
                <i class="icon icon-lg icon-archives"></i>
                博客
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/tags"  >
                <i class="icon icon-lg icon-tags"></i>
                标签
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/categories"  >
                <i class="icon icon-lg icon-th-list"></i>
                分类
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://github.com/tewuyiang" target="_blank" >
                <i class="icon icon-lg icon-github"></i>
                Github
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://weibo.com/u/5516635708/" target="_blank" >
                <i class="icon icon-lg icon-weibo"></i>
                Weibo
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://www.cnblogs.com/tuyang1129/" target="_blank" >
                <i class="icon icon-lg icon-link"></i>
                博客园
              </a>
            </li>
        
      </ul>
    </div>
  </div>
</aside>

    <main id="main">
        <header class="top-header" id="header">
    <div class="flex-row">
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light on" id="menu-toggle">
          <i class="icon icon-lg icon-navicon"></i>
        </a>
        <div class="flex-col header-title ellipsis">阻塞队列——ArrayBlockingQueue源码分析</div>
        
        <div class="search-wrap" id="search-wrap">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
                <i class="icon icon-lg icon-chevron-left"></i>
            </a>
            <input type="text" id="key" class="search-input" autocomplete="off" placeholder="输入感兴趣的关键字">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="search">
                <i class="icon icon-lg icon-search"></i>
            </a>
        </div>
        
        
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menuShare">
            <i class="icon icon-lg icon-share-alt"></i>
        </a>
        
    </div>
</header>
<header class="content-header post-header">

    <div class="container fade-scale">
        <h1 class="title">阻塞队列——ArrayBlockingQueue源码分析</h1>
        <h5 class="subtitle">
            
                <time datetime="2020-04-11T09:22:03.000Z" itemprop="datePublished" class="page-time">
  2020-04-11
</time>


	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/Java%E5%AE%B9%E5%99%A8/">Java容器</a></li></ul>

            
        </h5>
    </div>

    


</header>


<div class="container body-wrap">
    
    <aside class="post-widget">
        <nav class="post-toc-wrap post-toc-shrink" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#一、前言"><span class="post-toc-number">1.</span> <span class="post-toc-text">一、前言</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#二、正文"><span class="post-toc-number">2.</span> <span class="post-toc-text">二、正文</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-1-什么是阻塞队列"><span class="post-toc-number">2.1.</span> <span class="post-toc-text">2.1 什么是阻塞队列</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-2-ArrayBlockingQueue类的成员变量"><span class="post-toc-number">2.2.</span> <span class="post-toc-text">2.2 ArrayBlockingQueue类的成员变量</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-3-ArrayBlockingQueue的构造方法"><span class="post-toc-number">2.3.</span> <span class="post-toc-text">2.3 ArrayBlockingQueue的构造方法</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-4-入队方法的实现"><span class="post-toc-number">2.4.</span> <span class="post-toc-text">2.4 入队方法的实现</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-5-出队方法的实现"><span class="post-toc-number">2.5.</span> <span class="post-toc-text">2.5 出队方法的实现</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-6-ArrayBlockingQueue的优缺点"><span class="post-toc-number">2.6.</span> <span class="post-toc-text">2.6 ArrayBlockingQueue的优缺点</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#三、总结"><span class="post-toc-number">3.</span> <span class="post-toc-text">三、总结</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#四、参考"><span class="post-toc-number">4.</span> <span class="post-toc-text">四、参考</span></a></li></ol>
        </nav>
    </aside>


<article id="post-阻塞队列——ArrayBlockingQueue源码分析"
  class="post-article article-type-post fade" itemprop="blogPost">

    <div class="post-card">
        <h1 class="post-card-title">阻塞队列——ArrayBlockingQueue源码分析</h1>
        <div class="post-meta">
            <time class="post-time" title="2020-04-11 17:22:03" datetime="2020-04-11T09:22:03.000Z"  itemprop="datePublished">2020-04-11</time>

            
	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/Java%E5%AE%B9%E5%99%A8/">Java容器</a></li></ul>



            
<span id="busuanzi_container_page_pv" title="文章总阅读量" style='display:none'>
    <i class="icon icon-eye icon-pr"></i><span id="busuanzi_value_page_pv"></span>
</span>


        </div>
        <div class="post-content" id="post-content" itemprop="postContent">
            <h1 id="一、前言"><a href="#一、前言" class="headerlink" title="一、前言"></a>一、前言</h1><p>&emsp;&emsp;这几天准备研究一下<code>Java</code>中阻塞队列的实现。<code>Java</code>中的阻塞队列有七种，我准备逐一研究它们的源码，然后每一个阻塞队列写一篇分析博客，这是其中的第一篇。这篇博客就来说一说阻塞队列中我认为应该是最简单的一种——<code>ArrayBlockingQueue</code>。</p>
<br>

<h1 id="二、正文"><a href="#二、正文" class="headerlink" title="二、正文"></a>二、正文</h1><h2 id="2-1-什么是阻塞队列"><a href="#2-1-什么是阻塞队列" class="headerlink" title="2.1 什么是阻塞队列"></a>2.1 什么是阻塞队列</h2><p>&emsp;&emsp;在正式分析前，先简单介绍一下什么是阻塞队列。在说阻塞队列前，先要了解<strong>生产者消费者模式</strong>：</p>
<blockquote>
<p><strong>生产者消费者模式</strong>：生产者生产产品，将生产好的产品放入一个缓冲区域，消费者消费产品，它从缓冲区域获取生产者生产的产品进行消费。缓冲区域有容量限制，若缓存区域已经满了，则生产者需要停止生产，等待缓冲区有空闲位置后，再恢复生产；若缓冲区为空，则消费者需要等待，直到缓冲区中有产品后，才能进行消费；</p>
</blockquote>
<p>&emsp;&emsp;阻塞队列就是基于这种模式实现的<strong>队列型容器</strong>。阻塞队列的一般实现是：我们创建队列时，指定队列的容量，当队列中元素的个数已经满时，向队列中添加元素的线程将被阻塞，直到队列不满才恢复运行，将元素添加进去；当队列为空时，向队列获取元素的线程将被阻塞，直到队列不空才恢复运行，从队列中拿出元素。</p>
<p>&emsp;&emsp;以上是阻塞队列的一般实现，根据具体情况的不同，也会有所差异，比如有的是基于链表实现，有的是基于数组实现；有的是阻塞队列的没有容量限制（无界），而有的是有限制的（有界）。我们现在要分析的<strong>ArrayBlockingQueue就是一个基于数组实现的有界阻塞队列</strong>。下面我们就来从源码的角度分析一下<code>ArrayBlockingQueue</code>。</p>
<br>

<h2 id="2-2-ArrayBlockingQueue类的成员变量"><a href="#2-2-ArrayBlockingQueue类的成员变量" class="headerlink" title="2.2 ArrayBlockingQueue类的成员变量"></a>2.2 ArrayBlockingQueue类的成员变量</h2><p>&emsp;&emsp;我们先来了解一下<code>ArrayBlockingQueue</code>有哪些成员变量，知道它的成员变量对我们理解它的实现有很大的帮助：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 一个数组，用来存储放入队列中的元素 */</span></span><br><span class="line"><span class="keyword">final</span> Object[] items;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 此变量用来记录下一次从队列中拿出的元素，它在数组中的下标，可以理解为队列的头节点 */</span></span><br><span class="line"><span class="keyword">int</span> takeIndex;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 此变量存储下一次往队列中添加元素时，这个元素在数组中的下标，也就是记录队列尾的上一个位置 */</span></span><br><span class="line"><span class="keyword">int</span> putIndex;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 记录队列中元素的个数 */</span></span><br><span class="line"><span class="keyword">int</span> count;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 一个锁，用来保证向队列中插入、删除等操作的线程安全 */</span></span><br><span class="line"><span class="keyword">final</span> ReentrantLock lock;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 用来在队列为空时阻塞获取元素的线程，也就是用来阻塞消费者，</span></span><br><span class="line"><span class="comment"> * 这个变量叫notEmpty（不空），可以理解为队列空时将会被阻塞，不空时可以正常运行</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> Condition notEmpty;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 用来在队列满时阻塞添加元素的线程，也就是用来阻塞生产者</span></span><br><span class="line"><span class="comment"> * 这个变量叫notFull（不满），可以理解为队列满时将会阻塞，不满时可以正常运行</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> Condition notFull;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 遍历使用的迭代器 */</span></span><br><span class="line"><span class="keyword">transient</span> Itrs itrs = <span class="keyword">null</span>;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;通过以上成员变量，我们可以得知很多信息。首先，<code>ArrayBlockingQueue</code>是基于数组实现的阻塞队列，由于队列是从头部获取元素，尾部添加元素，所以定义了两个变量分别记录队列头在数组中的下标，以及插入新元素时的下标。除此之外，我们可以看到，它是使用<code>ReentrantLock</code>来实现的线程同步，在这个<code>lock</code>上定义了两个<code>Condition</code>对象，分别用来阻塞生产者和消费者，这是生产者消费者模式非常基本的一种实现方式。</p>
<br>

<h2 id="2-3-ArrayBlockingQueue的构造方法"><a href="#2-3-ArrayBlockingQueue的构造方法" class="headerlink" title="2.3 ArrayBlockingQueue的构造方法"></a>2.3 ArrayBlockingQueue的构造方法</h2><p>&emsp;&emsp;下面我们来看看它的构造方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 仅仅指定队列容量的构造方法</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ArrayBlockingQueue</span><span class="params">(<span class="keyword">int</span> capacity)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 调用下面那个构造方法，第二个参数默认为false，表示使用非公平锁</span></span><br><span class="line">    <span class="keyword">this</span>(capacity, <span class="keyword">false</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 此构造方法接收两个参数：</span></span><br><span class="line"><span class="comment"> * 1、capacity：指定阻塞队列的容量</span></span><br><span class="line"><span class="comment"> * 2、fair：指定创建的ReentrantLock是否是公平锁</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ArrayBlockingQueue</span><span class="params">(<span class="keyword">int</span> capacity, <span class="keyword">boolean</span> fair)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 容量必须大于0</span></span><br><span class="line">    <span class="keyword">if</span> (capacity &lt;= <span class="number">0</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException();</span><br><span class="line">    <span class="comment">// 初始化存储元素的数组</span></span><br><span class="line">    <span class="keyword">this</span>.items = <span class="keyword">new</span> Object[capacity];</span><br><span class="line">    <span class="comment">// 创建用于线程同步的锁lock，若fair为true，</span></span><br><span class="line">    <span class="comment">// 则此时创建的将是一个公平锁，反之则是非公平锁</span></span><br><span class="line">    lock = <span class="keyword">new</span> ReentrantLock(fair);</span><br><span class="line">    <span class="comment">// 初始化notEmpty变量，用以阻塞和唤醒消费者线程</span></span><br><span class="line">    notEmpty = lock.newCondition();</span><br><span class="line">    <span class="comment">// 初始化notFull变量，用以阻塞生产者线程</span></span><br><span class="line">    notFull =  lock.newCondition();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;上面的构造方法还是比较好理解的，唯一需要注意的地方就是用于线程同步的<code>lock</code>可以指定为公平锁，这也就意味着，线程的执行顺序将按时间排序，也就是先申请获取元素的线程，一定比后申请获取元素的线程，更先拿到元素，而向队列中放置元素的线程也是如此。如果我们需要这种先后顺序，可以将<code>lock</code>指定为公平锁，公平锁可以避免线程“饥饿”，但是公平锁比非公平锁的开销更大，因为强制要求每个线程排队，会导致阻塞和唤醒线程的次数大大增加，所以如果不是必要，最好还是使用非公平锁。</p>
<br>

<h2 id="2-4-入队方法的实现"><a href="#2-4-入队方法的实现" class="headerlink" title="2.4 入队方法的实现"></a>2.4 入队方法的实现</h2><p>&emsp;&emsp;接下来我们来看一看<code>ArrayBlockingQueue</code>的实现中，向队列中添加元素是如何实现的。<code>ArrayBlockingQueue</code>添加元素的方法有三个，分别是<code>add</code>，<code>offer</code>以及最重要的<code>put</code>。<code>add</code>和<code>offer</code>是<code>Queue</code>接口中定义的方法，任何一个实现了<code>Queue</code>接口的类都实现了这两个方法。但是<code>put</code>方法是阻塞队列才有的方法，它才是实现阻塞队列的核心方法之一。下面我们就先来分析看看<code>put</code>的实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">put</span><span class="params">(E e)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">    <span class="comment">// 判断元素是否为null，若为null将抛出异常</span></span><br><span class="line">    checkNotNull(e);</span><br><span class="line">    <span class="comment">// 获取锁对象lock</span></span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    <span class="comment">// 调用lock的lockInterruptibly方法加锁，lockInterruptibly可以响应中断</span></span><br><span class="line">    <span class="comment">// 加锁是为了防止多个线程同时操作队列，造成线程安全问题</span></span><br><span class="line">    lock.lockInterruptibly();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 如果当前队列中的元素的个数为数组长度，表示队列满了，</span></span><br><span class="line">        <span class="comment">// 这时调用notFull.await()让当前线程阻塞，也就是让生产者阻塞</span></span><br><span class="line">        <span class="comment">// 而此处使用while循环而不是if，是考虑到线程被唤醒后，队列可能还是满的</span></span><br><span class="line">        <span class="comment">// 所以线程被唤醒后，需要再次判断，若依旧是满的，则再次阻塞</span></span><br><span class="line">        <span class="keyword">while</span> (count == items.length)</span><br><span class="line">            notFull.await();</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 调用enqueue方法将元素加入数组中</span></span><br><span class="line">        enqueue(e);</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 释放锁</span></span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 此方法将新元素加入到数组中 */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">enqueue</span><span class="params">(E x)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 获得存储元素的数组</span></span><br><span class="line">    <span class="keyword">final</span> Object[] items = <span class="keyword">this</span>.items;</span><br><span class="line">    <span class="comment">// 将新元素x放入到数组中，且放入的位置就是putIndex指向的位置</span></span><br><span class="line">    items[putIndex] = x;</span><br><span class="line">    <span class="comment">// putIndex加1，如果超过了数组的最大长度，则将其置为0，也就是数组的第一个位置</span></span><br><span class="line">    <span class="keyword">if</span> (++putIndex == items.length)</span><br><span class="line">        putIndex = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// 元素数量+1</span></span><br><span class="line">    count++;</span><br><span class="line">    <span class="comment">// 因为我们已经向队列中添加了元素，所以可以唤醒那些需要获取元素的线程，也就是消费者</span></span><br><span class="line">    <span class="comment">// 之前说过，notEmpty就是用来阻塞和唤醒消费者的</span></span><br><span class="line">    notEmpty.signal();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 判断元素是否为null</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">checkNotNull</span><span class="params">(Object v)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (v == <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;以上就是<code>ArrayBlockingQueue</code>中<code>put</code>方法的实现。读了它的源码后我们可以发现，<code>put</code>的工作工程就是：<strong>向队列中添加一个新元素，若队列已经满了，则当前线程被阻塞，等待队列不满时被唤醒；当前线程成功添加元素后，将唤醒正在等待的消费者线程（如果有的话），消费者线程则从队列中获取元素。</strong>除了<code>put</code>方法外，阻塞队列还有两个方用以添加元素，就是<code>add</code>以及<code>offer</code>，这是<code>Queue</code>接口中定义的方法，也就是说并不是阻塞队列所特有的，所以这两个方法比较普通，我们简单地看一看即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">offer</span><span class="params">(E e)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 判断加入的元素是否为null，若为null将抛出异常</span></span><br><span class="line">    checkNotNull(e);</span><br><span class="line">    <span class="comment">// 获取锁对象</span></span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    <span class="comment">// 加锁防止线程安全问题，注意这里调用的是lock()方法，这个方法并不响应中断</span></span><br><span class="line">    <span class="comment">// 而之前的put方法会响应中断，以为put会阻塞，为了防止它长期阻塞，所以需要响应中断</span></span><br><span class="line">    <span class="comment">// 但是这个方法并不会被阻塞，所以不需要响应中断</span></span><br><span class="line">    lock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 若当前队列已满，则不进行添加，直接返回false，表示添加失败</span></span><br><span class="line">        <span class="keyword">if</span> (count == items.length)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 若队列不满，则直接调用enqueue方法添加元素，并返回true</span></span><br><span class="line">            enqueue(e);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 解锁</span></span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">add</span><span class="params">(E e)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 调用offer方法添加元素，若offer方法返回true表示添加成功，则此方法返回true</span></span><br><span class="line">    <span class="keyword">if</span> (offer(e))</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    <span class="comment">// 添加失败直接抛出异常</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(<span class="string">"Queue full"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;可以看到，这两个方法的实现比较简单。<code>offer</code>方法在队列满时直接放弃添加，返回<code>false</code>，若添加成功返回<code>true</code>；<code>add</code>方法直接调用<code>offer</code>方法添加元素，若添加失败，将会抛出异常。除了上面两个方法外，<code>ArrayBlockingQueue</code>还有一个比较特殊的方法，也是用来添加元素，并且在队列满时也会进行等待，但是并不会一直等待，而是等待指定的时间，这个方法是<code>offer</code>的重载方法，其代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 此方法用来阻塞式地添加元素，但是需要指定阻塞的超时时间</span></span><br><span class="line"><span class="comment"> * 1、timeout：需要阻塞时间的数量级，一个long类型的整数；</span></span><br><span class="line"><span class="comment"> * 2、unit：用以指定时间的单位，比如TimeUnit.SECONDS表示秒，</span></span><br><span class="line"><span class="comment"> *  	   若timeout为10，而unit为TimeUnit.SECONDS，则表示最多阻塞100秒</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">offer</span><span class="params">(E e, <span class="keyword">long</span> timeout, TimeUnit unit)</span></span></span><br><span class="line"><span class="function">    <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">	<span class="comment">// 判断元素是否为null</span></span><br><span class="line">    checkNotNull(e);</span><br><span class="line">    <span class="comment">// 获取线程需要阻塞的时间的纳秒值</span></span><br><span class="line">    <span class="keyword">long</span> nanos = unit.toNanos(timeout);</span><br><span class="line">    <span class="comment">// 获取锁对象</span></span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    <span class="comment">// 加锁，并且lockInterruptibly方法会响应中断</span></span><br><span class="line">    lock.lockInterruptibly();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 若当前队列中元素已满</span></span><br><span class="line">        <span class="keyword">while</span> (count == items.length) &#123;</span><br><span class="line">            <span class="comment">// 若等待的剩余时间小于0，表示超过了等待时间，则直接返回</span></span><br><span class="line">            <span class="keyword">if</span> (nanos &lt;= <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="comment">// 让当前线程等待指定的时间，使用notFull对象让线程等待一段时间</span></span><br><span class="line">            <span class="comment">// 方法会返回剩余的需要等待的时间</span></span><br><span class="line">            nanos = notFull.awaitNanos(nanos);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 调用enqueue方法将元素添加到数组中</span></span><br><span class="line">        enqueue(e);</span><br><span class="line">        <span class="comment">// 返回true表示添加成功</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 解锁</span></span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<br>

<h2 id="2-5-出队方法的实现"><a href="#2-5-出队方法的实现" class="headerlink" title="2.5 出队方法的实现"></a>2.5 出队方法的实现</h2><p>&emsp;&emsp;说完了向<code>ArrayBlockingQueue</code>中添加元素的方法，再说一说拿出队列中元素的方法。和添加元素类似，元素移出队列也有三个方法，分别是<code>remove</code>、<code>poll</code>以及阻塞队列中最关键的两个方法之一的<code>take</code>（另一个关键方法是<code>put</code>）。我们就先来看看<code>take</code>方法的实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">take</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">    <span class="comment">// 获取锁对象</span></span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    <span class="comment">// 使用lock对象加锁，lockInterruptibly方法会响应中断</span></span><br><span class="line">    <span class="comment">// 目的是防止线程一直在此处阻塞，无法退出</span></span><br><span class="line">    lock.lockInterruptibly();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 若当前队列中元素为0，则调用notEmpty对象的await()方法，</span></span><br><span class="line">        <span class="comment">// 让当前获取元素的线程阻塞，也就是阻塞消费者线程，直到被生产者线程唤醒</span></span><br><span class="line">        <span class="keyword">while</span> (count == <span class="number">0</span>)</span><br><span class="line">            notEmpty.await();</span><br><span class="line">        <span class="comment">// 调用dequeue方法获取队投元素，并直接返回</span></span><br><span class="line">        <span class="keyword">return</span> dequeue();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 解锁</span></span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 此方法用来获取队头元素，同时将它从数组中删除 */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> E <span class="title">dequeue</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 获取存储元素的数组</span></span><br><span class="line">    <span class="keyword">final</span> Object[] items = <span class="keyword">this</span>.items;</span><br><span class="line">    <span class="comment">// takeIndex记录的就是队头元素的下标，使用变量x记录它</span></span><br><span class="line">    E x = (E) items[takeIndex];</span><br><span class="line">    <span class="comment">// 将队头元素从数组中删除</span></span><br><span class="line">    items[takeIndex] = <span class="keyword">null</span>;</span><br><span class="line">    <span class="comment">// 队头元素删除后，原队头的下一个元素就成了新的队头，所以takeIndex + 1</span></span><br><span class="line">    <span class="comment">// 若takeIndex加1后超过数组的范围，则将takeIndex置为0，也就是循环使用数组空间</span></span><br><span class="line">    <span class="comment">// 为什么是加不是减，因为在数组中，队头在左边，队尾在右边</span></span><br><span class="line">    <span class="keyword">if</span> (++takeIndex == items.length)</span><br><span class="line">        takeIndex = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// 元素数量-1</span></span><br><span class="line">    count--;</span><br><span class="line">    <span class="comment">// 这里是在干嘛我也没仔细研究，好像是和队列的迭代器有关</span></span><br><span class="line">    <span class="keyword">if</span> (itrs != <span class="keyword">null</span>)</span><br><span class="line">        itrs.elementDequeued();</span><br><span class="line">    <span class="comment">// 当有元素出队后，队列不满，就可以被阻塞的生产者线程向队列中添加元素</span></span><br><span class="line">    notFull.signal();</span><br><span class="line">    <span class="comment">// 返回获取到的元素值</span></span><br><span class="line">    <span class="keyword">return</span> x;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;<code>take</code>方法和<code>put</code>方法有很多的相似之处，理解了<code>put</code>方法，那<code>take</code>方法也很好理解：<strong>获得阻塞队列中队头的元素，若队列为空，则当前线程被阻塞，直到有线程向队列中添加了元素，获取成功后，将队头元素从队列中删除，然后唤醒一个被阻塞的生产者线程（如果有的话）</strong>。下面再来看看<code>remove</code>以及<code>poll</code>方法的实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">poll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    <span class="comment">// 获取元素前线加锁</span></span><br><span class="line">    lock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 若队列为空，直接返回null，否则调用dequeue获取队头元素；</span></span><br><span class="line">        <span class="keyword">return</span> (count == <span class="number">0</span>) ? <span class="keyword">null</span> : dequeue();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 解锁</span></span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 此remove方法继承自父类</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">remove</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 调用poll获取并删除队头元素</span></span><br><span class="line">    E x = poll();</span><br><span class="line">    <span class="comment">// 若获取成功直接返回</span></span><br><span class="line">    <span class="keyword">if</span> (x != <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    <span class="comment">// 获取失败抛出异常</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NoSuchElementException();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;这两个方法实现非常简单，就不做过多解释了。下面我们再看看另一个获取元素的方法，这个方法获取元素时，需要指定超时时间，若队列为空，则当前线程将被阻塞，但是会在指定时间后返回，代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 方法参数timeout和unit的意义和之前指定超时时间的offer方法相同</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">poll</span><span class="params">(<span class="keyword">long</span> timeout, TimeUnit unit)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">    <span class="comment">// 计算超时时间的纳秒值</span></span><br><span class="line">    <span class="keyword">long</span> nanos = unit.toNanos(timeout);</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock lock = <span class="keyword">this</span>.lock;</span><br><span class="line">    lock.lockInterruptibly();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 若队列为空，则进行等待</span></span><br><span class="line">        <span class="keyword">while</span> (count == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 若剩余等待时间小于0，则表示超时了，直接返回null</span></span><br><span class="line">            <span class="keyword">if</span> (nanos &lt;= <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            <span class="comment">// 线程等待，并返回剩余等待时间</span></span><br><span class="line">            nanos = notEmpty.awaitNanos(nanos);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 若没有等待，或者在等待的过程中被唤醒，则调用dequeue方法获取队头元素</span></span><br><span class="line">        <span class="keyword">return</span> dequeue();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<br>

<h2 id="2-6-ArrayBlockingQueue的优缺点"><a href="#2-6-ArrayBlockingQueue的优缺点" class="headerlink" title="2.6 ArrayBlockingQueue的优缺点"></a>2.6 ArrayBlockingQueue的优缺点</h2><p>&emsp;&emsp;对于<code>ArrayBlockingQueue</code>的源码的阅读就止步于此，它的实现比较简单，看完上面的代码并理解，我认为就足够了。下面我们来讨论讨论它的优缺点。</p>
<p>&emsp;&emsp;首先是优点，我个人认为<code>ArrayBlockingQueue</code>没有什么比较明显的优点，除了实现简单。再说说缺点，那就比较明显了：</p>
<ul>
<li><code>ArrayBlockingQueue</code>只有一把锁，无论是添加还是获取元素使用的都是同一个锁对象，这也就导致了添加和获取不能同时执行，所以性能低下。但是，实际情况下，添加元素操作的是队尾，而获取元素操作的是队头，它们之间发生线程冲突的概率比较小，所以使用一把锁并不是一种好的实现方式。</li>
<li><code>ArrayBlockingQueue</code>基于数组实现，数组并不适用于随机删除元素，因为如果删除数组中间的元素，则这之后的元素都需要向前移动一个位置。而<code>ArrayBlockingQueue</code>支持<code>remove（Object o）</code>方法，删除指定元素。当然，这严格来讲并不是一个缺点，毕竟队列就是尾进头出，随机删除元素的操作虽然支持，但是一般不使用。</li>
</ul>
<br>

<h1 id="三、总结"><a href="#三、总结" class="headerlink" title="三、总结"></a>三、总结</h1><p>&emsp;&emsp;关于<code>ArrayBlockingQueue</code>的内容就说到这里。这种阻塞队列的实现较为简单，只要理解了<code>take</code>和<code>put</code>方法，基本上就足够了。但是，正因为它的实现比较简单，所以性能上并不是太好，毕竟内部只使用一把锁，所以这种阻塞队列用的也不是特别多。</p>
<br>

<h1 id="四、参考"><a href="#四、参考" class="headerlink" title="四、参考"></a>四、参考</h1><ul>
<li><a href="https://mp.weixin.qq.com/s/EN7qY1w4e8C0ZXiP7i82TA" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/EN7qY1w4e8C0ZXiP7i82TA</a></li>
</ul>

        </div>

        <blockquote class="post-copyright">
    
    <div class="content">
        
<span class="post-time">
    最后更新时间：<time datetime="2020-04-11T16:51:51.414Z" itemprop="dateUpdated">2020-04-12 00:51:51</time>
</span><br>


        
        世界是个球，前方总有路！
        
    </div>
    
    <footer>
        <a href="http://tewuyiang.gitee.io/blog">
            <img src="/blog/img/avatar.jpg" alt="特务依昂">
            特务依昂
        </a>
    </footer>
</blockquote>

        


        <div class="post-footer">
            
	<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/blog/tags/Java%E5%AE%B9%E5%99%A8/" rel="tag">Java容器</a></li></ul>


            
<div class="page-share-wrap">
    

<div class="page-share" id="pageShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&title=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&pic=http://tewuyiang.gitee.io/blog/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&title=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&source=一个未来程序员的博客~~~" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&via=http://tewuyiang.gitee.io/blog" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>



    <a href="javascript:;" id="shareFab" class="page-share-fab waves-effect waves-circle">
        <i class="icon icon-share-alt icon-lg"></i>
    </a>
</div>



        </div>
    </div>

    
<nav class="post-nav flex-row flex-justify-between">
  
    <div class="waves-block waves-effect prev">
      <a href="/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94LinkedBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/" id="post-prev" class="post-nav-link">
        <div class="tips"><i class="icon icon-angle-left icon-lg icon-pr"></i> Prev</div>
        <h4 class="title">阻塞队列——LinkedBlockingQueue源码分析</h4>
      </a>
    </div>
  

  
    <div class="waves-block waves-effect next">
      <a href="/blog/%E6%B5%85%E6%9E%90B%E6%A0%91%E3%80%81B-%E6%A0%91%E4%BB%A5%E5%8F%8AMySQL%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8/" id="post-next" class="post-nav-link">
        <div class="tips">Next <i class="icon icon-angle-right icon-lg icon-pl"></i></div>
        <h4 class="title">MySQL中的索引为什么使用B+树实现</h4>
      </a>
    </div>
  
</nav>



    




















</article>



</div>

        <footer class="footer">
    <div class="top">
        
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        站点总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        站点总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


        <p>
            
                <span><a href="/blog/atom.xml" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>
            
            <span>博客内容遵循 <a rel="license noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议</a></span>
        </p>
    </div>
    <div class="bottom">
        <p><span>特务依昂 &copy; 2015 - 2020</span>
            <span>
                
                Power by <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/yscoder/hexo-theme-indigo" target="_blank">indigo</a>
            </span>
        </p>
    </div>
</footer>

    </main>
    <div class="mask" id="mask"></div>
<a href="javascript:;" id="gotop" class="waves-effect waves-circle waves-light"><span class="icon icon-lg icon-chevron-up"></span></a>



<div class="global-share" id="globalShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&title=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&pic=http://tewuyiang.gitee.io/blog/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&title=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&source=一个未来程序员的博客~~~" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《阻塞队列——ArrayBlockingQueue源码分析》 — 博客主页&url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/&via=http://tewuyiang.gitee.io/blog" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://tewuyiang.gitee.io/blog/%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E2%80%94%E2%80%94ArrayBlockingQueue%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>


<div class="page-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <p>扫一扫，分享到微信</p>
    <img src="" alt="微信分享二维码">
</div>




    <script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>
<script>
var BLOG = { ROOT: '/blog/', SHARE: true, REWARD: false };


</script>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/main.min.js"></script>


<div class="search-panel" id="search-panel">
    <ul class="search-result" id="search-result"></ul>
</div>
<template id="search-tpl">
<li class="item">
    <a href="{path}" class="waves-block waves-effect">
        <div class="title ellipsis" title="{title}">{title}</div>
        <div class="flex-row flex-middle">
            <div class="tags ellipsis">
                {tags}
            </div>
            <time class="flex-col time">{date}</time>
        </div>
    </a>
</li>
</template>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/search.min.js" async></script>






<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



<script>
(function() {
    var OriginTitile = document.title, titleTime;
    document.addEventListener('visibilitychange', function() {
        if (document.hidden) {
            document.title = '人呢，怎么不见了！';
            clearTimeout(titleTime);
        } else {
            document.title = '(つェ⊂)咦!欢迎回来!';
            titleTime = setTimeout(function() {
                document.title = OriginTitile;
            },2000);
        }
    });
})();
</script>



</body>
</html>
